home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / objcissu.lha / exception-handling < prev    next >
Text File  |  1993-03-01  |  26KB  |  605 lines

  1. Paul Murphy <murphy@gun.com> just forwarded this to me.  FYI.  10/14/92 gsk
  2.  
  3. Position Paper
  4. ECOOP'91 WORKSHOP ON
  5. EXCEPTION HANDLING AND OBJECT-ORIENTED PROGRAMMING
  6. July 1991
  7. Geneva, Switzerland
  8.  
  9. Brad Cox
  10. 203 426 1875
  11. cox@stepstone.com
  12. CI$ 71230,647
  13. The Stepstone Corporation
  14. 75 Glen Road
  15. Sandy Hook CT 06482
  16.  
  17. This consists of selected sections from a much longer paper,
  18. `TaskMaster', which discusses a number of environmental features,
  19. including exception handling and lightweight multi-tasking, that can
  20. be supported in any C-based language with a single uniform language
  21. extension called `action expressions'.
  22.  
  23. The first section of this document discusses exception handling as a
  24. topic unto itself. The final section introduces action expression
  25. syntax and semantics, as is being considered for adoption as an
  26. extension to the Objective-C programming environment.
  27.  
  28. Exception handling
  29.  
  30. Consider a subroutine, main(), which calls foo(), which calls bar().
  31. The runtime stack that underlies the C runtime environment extends to
  32. record that main has called foo and that foo has called bar. Then it
  33. retracts as bar returns to foo and as foo returns to main. The same
  34. call/return path is used unconditionally, regardless of whether the
  35. subroutines ran successfully or failed because of an exception.
  36.  
  37. The absence of a way of handling exceptions explicitly, independently
  38. from normal processing, is a severe obstacle to software quality and
  39. reusability. Since subroutines routines return the same way,
  40. regardless of whether they succeed or fail, a method that should
  41. return a handle to a new object might instead return an error code to
  42. indicate that it could not, perhaps because of insufficient memory.
  43. Since any such call might fail, the caller must check every return
  44. value, reporting any failures to higher levels with similar means.
  45. This is sufficiently tedious that it is neglected, allowing unhandled
  46. exceptions to crash the application.
  47.  
  48. An `exception' is a situation where a computation does not proceed as
  49. planned, perhaps because of I/O errors, inability to allocate a new
  50. object because of insufficient memory, or defects in the software
  51. itself. `Exception handling' is a language/environmental feature that
  52. reserves the normal subroutine/message return channel exclusively for
  53. normal processing. Routines that return normally can be assumed to
  54. have succeeded, since those that fail will return via a independent
  55. channel reserved for exceptions. Low-level routines never fail by
  56. returning an error code for the caller to decipher, but by `raising an
  57. exception'. Higher level routines establish code fragments, `exception
  58. handlers', that will receive control if the exception they are to
  59. handle is raised by a lower-level routine.
  60.  
  61. The following shows how exception handling might be done in C, in
  62. order to show the limitations of this solution and how these
  63. limitations are addressed in TaskMaster. TRY() is a C macro that uses
  64. setjmp() to record the machine's register settings before entering the
  65. computation that might fail; the foo subroutine.
  66.  
  67. main() {
  68.     TRY() {
  69.         int v = foo();
  70.         <normal processing<
  71.     } HANDLE(OUTOFMEMORYEXCEPTION) {
  72.         <handle low memory exceptions<
  73.     } HANDLE(IOEXCEPTION) {
  74.         <handle IO failure exceptions<
  75.     } OTHERWISE() {
  76.         <handle any other exceptions<
  77.     }
  78. }
  79. foo() {
  80.     TRY() {
  81.         int v = bar();
  82.         <normal processing<
  83.     } HANDLE(OUTOFMEMORYEXCEPTION);
  84. }
  85. bar() {
  86.     id newObject = [SomeClass new];
  87.     <normal processing<
  88. }
  89.  
  90. If the foo() subroutine, or any subroutine that it calls, fails
  91. because of some exception, it does not return normally. Instead, it
  92. `raises an exception', which returns directly to the higher-level
  93. routine, by using longjmp() to return directly, bypassing the
  94. intervening subroutines altogether. The TRY() macro detects the
  95. abnormal return and transfers to the appropriate handler, which
  96. handles the exception in some case-specific fashion. By having the
  97. TRY() macro manage saved register settings on LIFO stack, exception
  98. handlers can be nested so that exceptions are presented to their
  99. handlers in deepest-first sequence. The low-level exception handlers
  100. may choose to pass control to the next higher-level handler by popping
  101. the higher-level registers from the exception handler's stack and
  102. calling longjmp() again.
  103.  
  104. The problems with this scheme will be familiar to anyone who has used
  105. it extensively. Since the exception handlers unconditionally execute
  106. in the context of the calling routine, as opposed to as a subroutine
  107. of the routine that detected the exception, information is
  108. unconditionally lost as to what sequence of calls triggered the
  109. exception. For example, foo's OUTOFMEMORYEXCEPTION handler can
  110. determine that bar, or one of its subroutines, failed because of
  111. insufficient memory. But it cannot tell which one, because the stack
  112. has been rewound before the handler has been invoked. This makes it
  113. useless for exception handlers to invoke process inspectors
  114. (debuggers), since the debugging information has been unconditionally
  115. discarded.
  116.  
  117. TaskMaster takes a different approach. It exports the handler to the
  118. exception, rather than the other way around. By invoking the exception
  119. handler as a subroutine of the exception, the stack is never erased
  120. until the user's code has had a chance to use it. One way to think
  121. about the difference is that TaskMaster exception handlers are first
  122. class C subroutines, not compound statements as in the preceding
  123. example. They are passed as function pointers in the exception handler
  124. stack and invoked as subroutines by the logic for raising an
  125. exception.
  126.  
  127. Action expressions are a compiler-supported enhancement to deal with
  128. the fact that code that uses function pointers extensively can be hard
  129. to write and nearly impossible to understand later. This extension,
  130. which is planned for a future compiler release and is not yet
  131. available, would let this example be coded like this:
  132.  
  133. main() {
  134.     [{ int v = foo();
  135.         <normal processing<
  136.     } ifException:{
  137.         if (OUTOFMEMORYEXCEPTION) {
  138.         <handle low memory exceptions<
  139.         } else if (IOEXCEPTION) {
  140.         <handle IO failure exceptions<
  141.         } else {
  142.         <handle any other exceptions<
  143.         }
  144.     }];
  145. foo() {
  146.     [{ int v = bar();
  147.         <normal processing<
  148.     } ifException: {
  149.         <handle exceptions<
  150.     }];
  151. }
  152. bar() {
  153.     id newObject = [SomeClass new];
  154.     <normal processing<
  155. }
  156.  
  157. The statements that look like C compound statements used as
  158. expressions, in {bold braces}, are action expressions, which will be
  159. described in the next section. Their relevance to exception handling
  160. is that
  161.  
  162. The code to be protected from exceptions, and the code for providing
  163. that protection, can be written alongside each other in a familiar
  164. readable fashion, without the syntactic clutter of working with
  165. function pointers directly.
  166.  
  167. The compiler will generate the necessary boiler plate automatically,
  168. transforming the action expressions into function definitions that the
  169. underlying C compiler knows how to handle.  Although actions look
  170. syntactically like expressions, they are semantically analogous to
  171. function pointers that the exception handler can invoke as a
  172. subroutine of the exception, as opposed to within the scope of the
  173. calling site.
  174.  
  175. TaskMaster's run-time support for this style of exception handling is
  176. in place today, and can be used by following the code generation
  177. strategy that the extended compiler will use; coding action
  178. instantiation statements by hand.
  179.  
  180. A final TaskMaster feature is that exception handling is closely
  181. integrated with lightweight multitasking. Each task maintains an
  182. independent stack of exception handlers that inherits any exception
  183. handlers of its parent task. For example, a parent task can provide
  184. supply handlers of last resort for exceptions in its subtasks.
  185. TaskMaster automatically initializes the root task with a default
  186. handler for all possible exceptions.
  187.  
  188. This handler of last resort features an interactive task inspector
  189. with interactive debugging facilities. A programmer can use the
  190. inspector to examine the call history that led to the exception and
  191. specify whether to exit the application, produce a file suitable for
  192. detailed debugging, or to continue in spite of the exception.
  193.  
  194. The inspector is based on a library of routines that interpret C call
  195. histories in terms that a programmer can easily understand. For
  196. example, call histories are not presented as hexadecimal numbers but
  197. in symbolic terms. Subroutine and selector names are spelled out with
  198. all arguments decoded. Object references are presented in terms of the
  199. object's class name and its address, string pointers are presented in
  200. terms of the string's contents, and so forth. These decoding
  201. facilities are based on a library of platform-dependent routines in
  202. the TaskMaster PDL. These routines support such platform-dependent
  203. operations as loading the application's symbol table. They also
  204. provide the heuristic rules that determine which format should be used
  205. in presenting the otherwise untyped numbers in a C call stack.
  206.  
  207. Apart from such convenience features, the exception handling is not
  208. particularly dependent on the target platform. Exception handling is
  209. based on a pair of routines, setjmp() and longjmp(), in the standard C
  210. run time library. Nor is it particularly dependent on multi-tasking,
  211. except that bundling exception handling with multi-tasking makes it
  212. possible for subtasks to manage exceptions independently from other
  213. tasks. Nor is exception handling specific to Objective-C. Its benefits
  214. are equally germane to ordinary C programs. This is another reason why
  215. TaskMaster's exception handling facilities are brought forth through
  216. two API's, a message-based API for users who want to treat exceptions
  217. as objects and a function-based API for those who want to treat them
  218. as functions.
  219.  
  220. Action expressions
  221.  
  222. Action expressions in Objective-C are related to block expressions in
  223. Smalltalk, with differences that adapt to the constraints of
  224. stack-based languages like C. Action expressions are a way to express
  225. actions, or deferred computations; computations to be written at one
  226. place but invoked from another.
  227.  
  228. The classical examples of a deferred computation is a computation that
  229. a collection is to perform on each of its members or that a menu is to
  230. perform when selected. As the following examples show, action
  231. expressions are generally useful, especially for defining menus,
  232. operating on collection members, handling exceptions, and defining
  233. lightweight tasks:
  234.  
  235. [ aMenu str:"Open" action:{ code to do a menu operation }];
  236. [ { code that might fail } ifException: { code to handle the exception } ];
  237. [ anyCollection do:{ code to be applied to each member } ];
  238. [ { code to run as a separate task } forkWith:2, arg1, arg2];
  239.  
  240. Here is an a simpler example of how action expressions help to express
  241. a deferred computation. In this example, a printf() statement is to be
  242. passed to a subroutine, bar(), which will execute it at its
  243. convenience. Notice that the deferred computation is written right
  244. inside the foo subroutine, just like any C expression. But it is not
  245. to be executed there. The action is passed as an argument to the bar
  246. routine, so that bar can decide whether, and when, to invoke it later.
  247.  
  248. extern int aGlobal;
  249. foo(aFormal)
  250.     int aLocal;
  251.  
  252.     <long, involved computation<
  253.  
  254.     /*
  255.      * Pass this action to bar, which may run it later
  256.      */
  257.     bar({ int formalArg; | printf(<, aGlobal, aFormal, aLocal, formalArg);});
  258.  
  259.     <long, involved computation<
  260. }
  261.  
  262. An action expression can be thought of as any legal C compound
  263. statement, used in a context where an expression is otherwise
  264. expected:
  265.  
  266. Action expressions are written in-line, exactly like an ordinary C or
  267. Objective-C expression. In this case, the action expression is an
  268. argument to the foo subroutine call.
  269.  
  270. Action expressions can freely reference any and all data within the
  271. expression's enclosing scope, such as the aGlobal, aFormal, and aLocal
  272. variables in this example.
  273.  
  274. Evaluation of an action expression produces an object; an instance of
  275. class Action. For example, the foo subroutine will receive an instance
  276. of class Action as its formal argument, anAction.
  277.  
  278. Invocation of an action occurs separately, just as invocation of a
  279. function via a function pointer is separate from the act of defining
  280. the function that it points to. The bar routine might invoke the
  281. printf statement with the message expression, [anAction value], in
  282. which formalArg will be nil. If it invokes it as [anAction
  283. value:aValue], formalArg will contain aValue.
  284.  
  285. Action expressions can receive formal arguments from the message that
  286. invokes them, such as formalArg in this example. These are analogous
  287. to subroutine arguments. If formal arguments are to be used, they are
  288. declared in the block expression as in this example, where the | is a
  289. place-holder for an as-yet-undecided syntactic delimiter.
  290.  
  291. Action expression's usefulness becomes most obvious in contrast with
  292. how this example would be coded in ordinary C, using function
  293. pointers:
  294.  
  295. extern aGlobal;
  296. static dummyFv, dummyLv;
  297. static dummyFn(formalArg)
  298. {
  299.     printf("<", aGlobal, dummyFv, dummyLv, formalArg);
  300. }
  301. foo(aFormal) {
  302.     int aLocal;
  303.  
  304.     <long, involved computation<
  305.  
  306.     /*
  307.      * Pass dummyFn to bar as a function pointer
  308.      * so that bar can run it later
  309.      */
  310.     dummyFv = aFormal;
  311.     dummyLv = aLocal;
  312.     bar(dummyFn);
  313.  
  314.     <long involved computation<
  315. }
  316.  
  317. This is less desirable than the original code for reasons referred to
  318. earlier as syntactic clutter.
  319.  
  320. The computation is no longer in-line, inside the foo routine. The
  321. reader must be extremely careful to see that this code is packaging a
  322. printf() statement for execution by bar().
  323.  
  324. The enclosing scope (foo) cannot pass data to the computation in a
  325. clean, readable fashion. It must use extraneous global variables, the
  326. dummyFv and dummyLv symbols in this example, to export data from its
  327. internal scope to the external function, dummyFn. These global
  328. variables are an obstacle to recursion and a rich opportunity for hard
  329. to debug race conditions should foo be used by multiple tasks.
  330.  
  331. Objective-C actions have a key restriction that is not present with
  332. Smalltalk blocks. The code inside a action accesses copies of the
  333. variables that it references in the enclosing scope. These copies are
  334. made when the action is instantiated, not when it is invoked, as is
  335. the case with Smalltalk Blocks. The copies are stored as indexed
  336. instance variables inside the Action object and not in the enclosing
  337. scope (foo's stack frame).
  338.  
  339. When the underlying C function is invoked, these variables are
  340. exported to the function via a structure pointer, as can be seen in
  341. the following example. For example, the aGlobal, aFormal, and aLocal
  342. variables in this example are copied when the action is created (i.e.
  343. just before bar is called), not when the deferred computation is
  344. invoked (inside bar). Objective-C action expressions do not share
  345. memory with their enclosing scope, they cannot export changes to the
  346. enclosing scope as in Smalltalk. Changes to action variables is
  347. ineffective, since the change affects a copy, not the original.
  348.  
  349. This may have made the simple seem unduly complicated. What is going
  350. on here can seen by examining the C code that the compiler would emit
  351. for this example:
  352.  
  353. static void fn(struct { int aGlobal, aFormal, aLocal; } *c, int formalArg)
  354. {
  355.     printf(<, c->aGlobal, c->aFormal, c->aLocal, formalArg);
  356. }
  357. foo(aFormal) {
  358.     extern int aGlobal;
  359.     int aLocal;
  360.  
  361.     <long, involved computation<
  362.  
  363.     bar(createAction(fn, 3, aGlobal, aFormal, aLocal));
  364.  
  365.     <long, involved computation<
  366.  
  367. }
  368.  
  369. Of course, this example was intentionally simplified by choosing an
  370. example in which everything is of type int. This does not mean that
  371. actions will only be usable for integers; just that the adjustments
  372. that the compiler would emit for other types seem obvious. Until the
  373. compiler has been enhanced to emit this code automatically, this
  374. example shows what a present-day Objective-C user would write to use
  375. TaskMaster's action-based library facilities today.
  376.  
  377.  
  378. Date: Mon, 12 Oct 1992 13:46:03 -0500
  379. To: gnu-objc@prep.ai.mit.edu
  380. From: bradcox@sitevax.gmu.edu (Brad Cox)
  381. Subject: Action Expressions (exception handling, multitasking)
  382. Cc: Bruce Nilo <bruce@ictv.com>
  383.  
  384. In Re: Your mission, should you choose to accept it. . Bruce Nilo
  385. <bruce@ictv.com> writes
  386.  
  387. NeXT has half heartedly implemented an "Exception Handling" facility.  
  388. It basically consists of some macros, and the use of setjmp() and  
  389. longjmp(). An error handling facility should be specified,  
  390. implemented, and adhered to throughout the runtime system.
  391.  
  392. I agree wholeheartedly! I joined this list primarily to encourage
  393. extensions to Objective-C of precisely this nature.
  394.  
  395. I made substantial progress on the run-time part of this problem at Stepstone
  396. several years ago, but never managed to complete the language extensions
  397. (upwards compatible) to make them broadly useful. 
  398.  
  399. <Taskmaster Document> "Action expressions in Objective-C are similar to
  400. block expressions in Smalltalk, with differences to adapt to the
  401. constraints of stack-based languages like C. Action expressions are a way
  402. to express actions, or deferred computations; computations to be written at
  403. one place but invoked from another."
  404.  
  405. This document, which describes the (implemented) runtime components and
  406. (unimplemented) syntactic extensions, would be useful in considering
  407. language and/or runtime extensions. 
  408.  
  409. I'll be glad to email a copy to those planning to  work on such extentions. 
  410. (Please...only if you're planning to do actual work!)
  411. ===
  412. Brad Cox, Ph.D; Program on Social and Organizational Learning; George Mason
  413. University; Fairfax VA 22030; 703 691 3187 direct; 703 993 1142 reception;
  414. bradcox@sitevax.gmu.edu
  415. ---
  416. Information Age Consulting; 13668 Bent Tree Circle #203; Centreville VA
  417. 22020;           703 968 8229 home; 703 968 8798 fax; bradcox@infoage.com
  418.  
  419. Date: Thu, 15 Oct 92 04:59:00 -0400
  420. From: rms@gnu.ai.mit.edu (Richard Stallman)
  421. To: gsk@marble.com
  422. Cc: gnu-objc@prep.ai.mit.edu
  423. Subject: action expressions
  424.  
  425. GNU C supports nested functions.  In 2.3, these should work in
  426. Objective C.  This supplies most of the mechanism for creating action
  427. objects if you want them.  In fact, I expect one can go the rest of
  428. the way with macros, if you don't mind a different syntax:
  429.  
  430. #define make_action(name, body)
  431.  ({ id __temp = <create an empty action object>;
  432.     void name () { body }
  433.     <store &name into __temp>;
  434.     __temp; })
  435.  
  436. I've omitted the backslashes, and left stubs for where Objective C
  437. constructs are needed since I don't know them.
  438.  
  439. This technique requires you to give a unique name each time you write
  440. an action expression.  That could be avoided with an improvement in
  441. macro power.
  442.  
  443. Date: Thu, 15 Oct 92 05:02:24 -0400
  444. From: rms@gnu.ai.mit.edu (Richard Stallman)
  445. To: gsk@marble.com
  446. Cc: gnu-objc@prep.ai.mit.edu
  447. Subject: exceptions
  448.  
  449. There seems to be a concensus that (1) exceptions should work by
  450. exiting to the level where the handler was set up, and (2) running a
  451. debugger is a completely independent matter from handling exceptions.
  452.  
  453. I've seen systems where there was an attempt to permit handlers to
  454. look at the environment of the exception.  The problem is that the
  455. handler can't do anything useful except a goto, unless it understands
  456. what was going on at the place that got the exception.  And the whole
  457. idea is that the handler shouldn't have to know that.  So an exception
  458. facility that always does a goto is sufficient.
  459.  
  460. There are various plans to implement exception handling in GCC for the
  461. sake of various languages, and it will surely get done sooner or later.
  462. It will be easy to support in Objective C once the mechanism is present.
  463.  
  464. Date: Thu, 15 Oct 92 05:25:13 -0400
  465. From: rms@gnu.ai.mit.edu (Richard Stallman)
  466. To: rms@gnu.ai.mit.edu
  467. Cc: gsk@marble.com, gnu-objc@prep.ai.mit.edu
  468. Subject: exceptions
  469.  
  470. I see my message was not clearly written and might have been
  471. confusing.
  472.  
  473. There seems to be a consensus among most language designers that (1)
  474. exceptions should work by exiting to the level where the handler was
  475. set up, and (2) running a debugger is a completely independent matter
  476. from handling exceptions.  Brad Cox seems to disagree--but I agree
  477. with the general consensus, and that's how I plan to support
  478. exceptions in GCC.
  479.  
  480. Date: Thu, 15 Oct 1992 08:15:44 -0500
  481. To: rms@gnu.ai.mit.edu (Richard Stallman)
  482. From: bradcox@sitevax.gmu.edu (Brad Cox)
  483. Subject: Re: exceptions
  484. Cc: gsk@marble.com, gnu-objc@prep.ai.mit.edu
  485.  
  486. >There seems to be a consensus among most language designers that (1)
  487. >exceptions should work by exiting to the level where the handler was
  488. >set up, and (2) running a debugger is a completely independent matter
  489. >from handling exceptions.
  490.  
  491. The problem is most obvious when designing a 'default' exception handler;
  492. i.e. a piece of code internal to the EH package that will automatically
  493. catch exceptions globally if the programmer doesn't provide one of his own.
  494.  
  495. This global handler needs to run in the context of the exception to, for
  496. example, print a backtrace showing the calls that led to the exception. The
  497. same applies if somebody wants to override the exception to call a more
  498. sophisticated process inspector ( a 'debugger'), perhaps capable of
  499. examining and possibly even changing global shared state (such as the
  500. stack) and maybe even resuming the execution. For example, imagine invoking
  501. adb (or something better) from inside the handler.
  502.  
  503. I suspect that the concensus you speak of arose from the difficulty of
  504. writing exception handlers as subroutines rather than from more considered
  505. reasons. Action expressions are useful for many other things than exception
  506. handling. But once they become available, it becomes practical to
  507. reconsider solutions that weren't practical in their absence...like running
  508. exception handlers as subroutines of the exception. That is, exception
  509. handlers often need to access state  local to the scope of the calling
  510. site. This is clumsy if the handler is a subroutine, but easy if the
  511. handler is an action object because all variables are copied into the
  512. action object and passed to its handler as ordinary variables.
  513.  
  514. I've advocated a departure from concensus on this matter on the grounds of
  515. generality...potentially useful (albeit nontrivial to access) information;
  516. i.e. stack frames, are unconditionally discarded in the concensus solution
  517. that is retained by the action expression approach. 
  518.  
  519. And oh yes, the concensus approach is a concensus only for compiled
  520. stack-based languages like C, but not for non-stack-based languages like
  521. Smalltalk and (although I'm less sure of this; any Lisp experts in the
  522. crowd?) and Lisp. 
  523. Brad Cox; 703 691 3187 direct; 703 993 1142 reception;
  524. bradcox@sitevax.gmu.edu
  525.  
  526. From: billb@jupiter.fnbc.com (Bill Burcham)
  527. Date: Thu, 15 Oct 92 09:59:06 -0500
  528. To: bradcox@sitevax.gmu.edu (Brad Cox)
  529. Subject: Re: exceptions
  530. Cc: gnu-objc@prep.ai.mit.edu
  531.  
  532. Yeah, and there are also the problems of breaking a thread and never
  533. getting back from traditional exceptions.  Also, NeXT's approach uses
  534. int's to identify exceptions -- but they have no object to manage the
  535. allocation of these ints, so if I write some reusable class, I have to
  536. pick an int range at random (and pray that no one else has used or
  537. will ever use any of those same ints for their exceptions).
  538.  
  539. If we choose the consensus scheme (not that I am saying we _should_), then I believe it is important to provide an ExceptionBroker:
  540.  
  541. + (BOOL)setCodeBase:(int)base availableExceptions:(int)howmany;
  542. + registerErrorReporter:(void (*)(NXHandler *errorState))proc
  543.     forException:(STR)aName;
  544. + raise:(STR)exception data1:(void*)data1 data2:(void*)data2;
  545. + (BOOL)senderMayRaise:(STR)aName;
  546. + (int)exceptionNumber:(STR)aName;
  547.     
  548. #define EB_RegisterErrorReporter(proc, name) \
  549. [ExceptionBroker registerErrorReporter:(proc) \
  550.     forException:(aName)]
  551.     
  552. #define EB_RAISE(exception, d1, d2) \
  553. [ExceptionBroker raise:(exception) data1:(d1) data2:(d2)]
  554.  
  555. This protocol allows a class which will raise certain exceptions (or
  556. will produce instances which will produce certain exceptions) to check
  557. in +initialize (or -init) whether or not those exception identifiers
  558. are available to it.  If they are not, then the class or instance can
  559. set an ivar such as `BOOL classIsBroker' which can prevent subsequent
  560. instantiation, etc.
  561.  
  562. I will donate ExceptionBroker and helper class Exception to The
  563. Project if anyone is interested.
  564.  
  565. Bill
  566.  
  567. Date: Thu, 15 Oct 92 15:00:35 -0400
  568. From: rms@gnu.ai.mit.edu (Richard Stallman)
  569. To: bradcox@sitevax.gmu.edu
  570. Cc: gsk@marble.com, gnu-objc@prep.ai.mit.edu
  571. Subject: exceptions
  572.  
  573.     I suspect that the concensus you speak of arose from the difficulty of
  574.     writing exception handlers as subroutines
  575.  
  576. The difficulty you speak of is limited to C.  Most of the language
  577. design I'm talking about is for other languages that support nested
  578. functions, and could easily use that mechanism for running an
  579. exception handler as a subroutine, if that were desired.  There used
  580. to be such designs, as in PL/1, but they were not very useful and that
  581. led to the conclusion that handlers should always go back to the
  582. context where they were set up.
  583.  
  584.     This global handler needs to run in the context of the exception to, for
  585.     example, print a backtrace showing the calls that led to the exception.
  586.  
  587. The second part of the consensus is that handlers should not be the
  588. basis for debugging.
  589.  
  590. It is not very useful to print a backtrace.  The ways we deal with
  591. crashes is by either stopping the process or by making a core dump.
  592. Either way, you can get a backtrace or do various other useful
  593. things.  The way to do these is not with a handler.  Instead, the
  594. function that raises an exception will raise a signal when
  595. appropriate.
  596.  
  597.  
  598. I'm not going to support more than one exception handler mechanism in
  599. GCC unless there is a clear need.  I want to support just one, for all
  600. languages--to save work.  It may be that this mechanism can handle
  601. handlers that run as subroutines as well as handlers that jump,
  602. without much extra trouble.  But I would still design the handler
  603. construct in a new language to do jumps, at this point.
  604.  
  605.